
using System;
using System.Collections.Generic;
using System.Text;
using System.IO;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
using Microsoft.Xna.Framework.Net;
using Microsoft.Xna.Framework.Storage;
using Komires.MataliPhysics;

namespace MataliPhysicsDemo
{
    public class Demo : Game
    {
        string infoDrawFPSName;
        string infoPhysicsFPSName;
        string infoPhysicsObjectsName;
        string infoConstraintsName;
        string infoContactPointsName;
        string infoMenuName;
        Color infoDrawColor;
        Vector2 infoDrawPosition;

        StringBuilder infoDrawFPSNameBuilder;
        StringBuilder infoPhysicsFPSNameBuilder;
        StringBuilder infoPhysicsObjectsNameBuilder;
        StringBuilder infoConstraintsNameBuilder;
        StringBuilder infoContactPointsNameBuilder;
        int infoDrawFPSNameLength;
        int infoPhysicsFPSNameLength;
        int infoPhysicsObjectsNameLength;
        int infoConstraintsNameLength;
        int infoContactPointsNameLength;

        GraphicsDeviceManager graphics;

        public SpriteBatch spriteBatch;
        public SpriteFont spriteFont;
        public DemoFont3D DemoFont3D;

        public int SceneIndex;

        // Declare physics engine
        public PhysicsEngine Engine;

        // Declare scene object
        public IDemoScene Scene;

        // Declare menu object
        public MenuScene MenuScene;

        // Declare list of scene objects
        public List<IDemoScene> Scenes;

        // Declare dictionary of meshes
        public Dictionary<string, DemoMesh> Meshes;

        // Declare dictionary of textures
        public Dictionary<string, Texture2D> Textures;

        // Declare dictionary of menu descriptions
        public Dictionary<string, List<string>> Descriptions;

        public bool EnableMenu;

#if XBOX360
        GamePadState oldPadState;
#else
        KeyboardState oldKeyboardState;
        bool enablePrintScreen;
#endif

        public Demo()
        {
            Window.Title = "BasketBall Game Demo - Using Matali " + PhysicsEngine.Version + " (XNA)";
            graphics = new GraphicsDeviceManager(this);
            Content.RootDirectory = "Content";

            graphics.PreferredBackBufferWidth = 1900;
            graphics.PreferredBackBufferHeight = 1200;

            //graphics.SynchronizeWithVerticalRetrace = false;
            IsFixedTimeStep = false;

            Window.ClientSizeChanged += new EventHandler<EventArgs>(Window_ClientSizeChanged);

            infoDrawFPSName = "Draw FPS: ";
            infoPhysicsFPSName = "Physics FPS: ";
            infoPhysicsObjectsName = "Physics objects: ";
            infoConstraintsName = "";
            infoContactPointsName = " ";
            infoMenuName = "F1: Menu";
            infoDrawColor = Color.White;

            infoDrawFPSNameBuilder = new StringBuilder(infoDrawFPSName);
            infoPhysicsFPSNameBuilder = new StringBuilder(infoPhysicsFPSName);
            infoPhysicsObjectsNameBuilder = new StringBuilder(infoPhysicsObjectsName);
            infoConstraintsNameBuilder = new StringBuilder(infoConstraintsName);
            infoContactPointsNameBuilder = new StringBuilder(infoContactPointsName);
            infoDrawFPSNameLength = infoDrawFPSNameBuilder.Length;
            infoPhysicsFPSNameLength = infoPhysicsFPSNameBuilder.Length;
            infoPhysicsObjectsNameLength = infoPhysicsObjectsNameBuilder.Length;
            infoConstraintsNameLength = infoConstraintsNameBuilder.Length;
            infoContactPointsNameLength = infoContactPointsNameBuilder.Length;

            DemoFont3D = null;

            // Create a new physics engine
            Engine = new PhysicsEngine("Engine");

            Scene = null;

            // Create a new menu object
            MenuScene = new MenuScene(this, "Menu", 1, null);

            // Create a new list of scene objects
            Scenes = new List<IDemoScene>();

            // Create a new dictionary of meshes
            Meshes = new Dictionary<string, DemoMesh>();

            // Create a new dictionary of textures
            Textures = new Dictionary<string, Texture2D>();

            // Create a new dictionary of menu descriptions
            Descriptions = new Dictionary<string, List<string>>();

            EnableMenu = false;
            oldKeyboardState = Keyboard.GetState();
        }

        void Window_ClientSizeChanged(object sender, EventArgs e)
        {
            for (int i = 0; i < Scenes.Count; i++)
                Scenes[i].UpdateResources();
        }

        protected override void Initialize()
        {
            base.Initialize();
        }

        protected override void LoadContent()
        {
            // Create a new SpriteBatch, which can be used to draw textures.
            spriteBatch = new SpriteBatch(GraphicsDevice);

            // TODO: use this.Content to load your game content here
            spriteFont = Content.Load<SpriteFont>("Fonts\\Default");

            Meshes.Clear();

            Meshes.Add("Box", new DemoMesh(this, Content.Load<Model>("Meshes\\Box")));
            Meshes.Add("Test", new DemoMesh(this, Content.Load<Model>("Meshes\\complete_basket")));
            Meshes.Add("CylinderY", new DemoMesh(this, Content.Load<Model>("Meshes\\CylinderY")));
            Meshes.Add("Cylinder2", new DemoMesh(this, Content.Load<Model>("Meshes\\complete_basket")));
            Meshes.Add("Sphere", new DemoMesh(this, Content.Load<Model>("Meshes\\Sphere")));
            Meshes.Add("ConeY", new DemoMesh(this, Content.Load<Model>("Meshes\\ConeY")));
            Meshes.Add("CapsuleY", new DemoMesh(this, Content.Load<Model>("Meshes\\CapsuleY")));
            Meshes.Add("Sky", new DemoMesh(this, Content.Load<Model>("Meshes\\Sky")));
            Meshes.Add("Basket", new DemoMesh(this, Content.Load<Model>("Meshes\\complete_basket")));

            Textures.Add("Default", Content.Load<Texture2D>("Materials\\cobblestone"));
            Textures.Add("Iron", Content.Load<Texture2D>("Materials\\Iron"));
            Textures.Add("Brass", Content.Load<Texture2D>("Materials\\Brass"));
            Textures.Add("Rubber", Content.Load<Texture2D>("Materials\\Rubber"));
            Textures.Add("Plastic1", Content.Load<Texture2D>("Materials\\Plastic1"));
            Textures.Add("Plastic2", Content.Load<Texture2D>("Materials\\Plastic2"));
            Textures.Add("Wood1", Content.Load<Texture2D>("Materials\\Wood1"));
            Textures.Add("Wood2", Content.Load<Texture2D>("Materials\\Wood2"));
            Textures.Add("Paint1", Content.Load<Texture2D>("Materials\\Paint1"));
            Textures.Add("Paint2", Content.Load<Texture2D>("Materials\\Paint2"));
            Textures.Add("Ground", Content.Load<Texture2D>("Materials\\Ground"));
            Textures.Add("Blue", Content.Load<Texture2D>("Materials\\Blue"));
            Textures.Add("Yellow", Content.Load<Texture2D>("Materials\\Yellow"));
            Textures.Add("Green", Content.Load<Texture2D>("Materials\\Green"));
            Textures.Add("Leaf", Content.Load<Texture2D>("Materials\\Leaf"));
            Textures.Add("Wall", Content.Load<Texture2D>("Materials\\wood_wall"));
            Textures.Add("Basket", Content.Load<Texture2D>("Materials\\basketball"));
            
            Textures.Add("DefaultFont", Content.Load<Texture2D>("Fonts\\DefaultFont"));

            Textures.Add("DefaultHeights", Content.Load<Texture2D>("Terrains\\DefaultHeights"));
            Textures.Add("DefaultFrictions", Content.Load<Texture2D>("Terrains\\DefaultFrictions"));
            Textures.Add("DefaultRestitutions", Content.Load<Texture2D>("Terrains\\DefaultRestitutions"));

            Textures.Add("DefaultShapes", Content.Load<Texture2D>("Menus\\Default\\Screens\\DefaultShapes"));
            Textures.Add("UserShapes", Content.Load<Texture2D>("Menus\\Default\\Screens\\UserShapes"));
            Textures.Add("Stacks", Content.Load<Texture2D>("Menus\\Default\\Screens\\Stacks"));
            Textures.Add("Ragdolls", Content.Load<Texture2D>("Menus\\Default\\Screens\\Ragdolls"));
            Textures.Add("Bridges", Content.Load<Texture2D>("Menus\\Default\\Screens\\Bridges"));
            Textures.Add("Building", Content.Load<Texture2D>("Menus\\Default\\Screens\\Building"));
            Textures.Add("AI", Content.Load<Texture2D>("Menus\\Default\\Screens\\AI"));
            Textures.Add("Helicopters", Content.Load<Texture2D>("Menus\\Default\\Screens\\Helicopters"));
            Textures.Add("Buildings", Content.Load<Texture2D>("Menus\\Default\\Screens\\Buildings"));
            Textures.Add("TerrainWithWater", Content.Load<Texture2D>("Menus\\Default\\Screens\\TerrainWithWater"));
            Textures.Add("Animation", Content.Load<Texture2D>("Menus\\Default\\Screens\\Animation"));
            Textures.Add("Cloth", Content.Load<Texture2D>("Menus\\Default\\Screens\\Cloth"));
            Textures.Add("Meshes", Content.Load<Texture2D>("Menus\\Default\\Screens\\Meshes"));

            DemoFont3D = new DemoFont3D(GraphicsDevice, this, "DefaultFont");

#if XBOX360
            // Create a new lists of menu descriptions
            Descriptions.Add("DefaultShapes", new List<string>() {
            "Scene:",
            "Shows default shapes",
            null, null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks: Player control",
            "Right ThumbSticks: Camera control",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("UserShapes", new List<string>() {
            "Scene:",
            "Shows user shapes, transparent objects, force fields, switches,",
            "static triangle meshes",
            null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks: Player control",
            "Right ThumbSticks: Camera control",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("Stacks", new List<string>() {
            "Scene:",
            "Shows stacking (Jenga, Pyramid, Wall)",
            null, null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks: Player control",
            "Right ThumbSticks: Camera control",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("Ragdolls", new List<string>() {
            "Scene:",
            "Shows ragdolls",
            null, null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks: Player control",
            "Right ThumbSticks: Camera control",
            "Y: Toggle camera",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("Bridges", new List<string>() {
            "Scene:",
            "Shows interactions between objects and bridge",
            null, null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks: Player control",
            "Right ThumbSticks: Camera control",
            "DPad: Vehicle remote control",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("Building", new List<string>() {
            "Scene:",
            "Shows interactions between player and vehicle, ragdoll, plant,",
            "building, particles",
            null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks, Right ThumbSticksDown: Player control",
            "Right ThumbSticks: Camera control",
            "Y: Toggle camera mode",
            "DPad: Vehicle remote control",
            "Left ThumbSticksDown + Collision with switch: Switch to driver seat",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("AI", new List<string>() {
            "Scene:",
            "Shows simple physical AI",
            null, null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks, Right ThumbSticksDown: Player control",
            "Right ThumbSticks: Camera control",
            "Y: Toggle camera mode",
            "DPad, DPad + X, X: Vehicle remote control, vehicle shoot",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("Helicopters", new List<string>() {
            "Scene:",
            "Shows physical waypoints and interactions between player",
            "and vehicle in the air",
            null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks, Right ThumbSticksDown: Player control",
            "Right ThumbSticks: Camera control",
            "Y: Toggle camera mode",
            "Collision with switch: Run vehicle",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("Buildings", new List<string>() {
            "Scene:",
            "Shows interactions between player and bridge, buildings",
            null, null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks, Right ThumbSticksDown: Player control",
            "Right ThumbSticks: Camera control",
            "Y: Toggle camera mode",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("TerrainWithWater", new List<string>() {
            "Scene:",
            "Shows interactions between player and objects, terrain, water",
            null, null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks, Right ThumbSticksDown: Player control",
            "Right ThumbSticks: Camera control",
            "Y: Toggle camera mode",
            "DPad: Vehicle remote control",
            "Left ThumbSticksDown + Collision with switch: Switch to driver seat",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("Animation", new List<string>() {
            "Scene:",
            "Shows physical animation",
            null, null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks, Right ThumbSticksDown: Player control",
            "Right ThumbSticks: Camera control",
            "Y: Toggle camera mode",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("Cloth", new List<string>() {
            "Scene:",
            "Shows point cloth",
            null, null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks, Right ThumbSticksDown: Player control",
            "Right ThumbSticks: Camera control",
            "Y: Toggle camera mode",
            "Collision with switch: Run machine",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });

            Descriptions.Add("Meshes", new List<string>() {
            "Scene:",
            "Shows static triangle meshes",
            null, null,
            "Input:",
            "Left Shoulder/Right Shoulder: Toggle scene",
            "B: Reset scene",
            "Left ThumbSticks, Right ThumbSticksDown: Player control",
            "Right ThumbSticks: Camera control",
            "Y: Toggle camera mode",
            "Right Trigger: Shoot",
            "Left Trigger: Grab objects" });
#else
            // Create a new lists of menu descriptions
            Descriptions.Add("Helicopters", new List<string>() {
            "Scene: Basketball Game"});

#endif

            // Create a new scene objects
            Scenes.Add(new HelicoptersScene(this, "BasketBall", 1, "xxx"));

            // Create a new physics scene for the menu object
            MenuScene.Create();
            MenuScene.Refresh(0.0);

            // Create a new physics scene for the scene object
            SceneIndex = 0;
            Scene = Scenes[SceneIndex];
            Scene.Create();
            Scene.Refresh(0.0);
        }

        protected override void UnloadContent()
        {
            // TODO: Unload any non ContentManager content here
            Meshes.Clear();
            Scenes.Clear();
            Textures.Clear();

            Engine.Factory.PhysicsSceneManager.RemoveAll();
        }

        protected override void Update(GameTime gameTime)
        {
            double time = gameTime.ElapsedGameTime.TotalSeconds;

            // TODO: Add your update logic here
            KeyboardState keyboardState = Keyboard.GetState();

            if (keyboardState.IsKeyDown(Keys.Escape))
                this.Exit();

            if (keyboardState.IsKeyDown(Keys.R) && oldKeyboardState.IsKeyUp(Keys.R))
            {
                Scene.Remove();
                Scene.Create();
                Scene.Refresh(0.0);
            }

            if (keyboardState.IsKeyDown(Keys.OemPlus) && oldKeyboardState.IsKeyUp(Keys.OemPlus))
            {
                SceneIndex = (SceneIndex + 1) % Scenes.Count;
                Scene = Scenes[SceneIndex];
                Scene.Create();
                Scene.Refresh(0.0);
            }

            if (keyboardState.IsKeyDown(Keys.OemMinus) && oldKeyboardState.IsKeyUp(Keys.OemMinus))
            {
                SceneIndex = (SceneIndex - 1) < 0 ? Scenes.Count - 1 : SceneIndex - 1;
                Scene = Scenes[SceneIndex];
                Scene.Create();
                Scene.Refresh(0.0);
            }

            oldKeyboardState = keyboardState;

            Scene.PhysicsScene.Simulate(time);

            base.Update(gameTime);
        }

        protected override void Draw(GameTime gameTime)
        {
            // TODO: Add your drawing code here
            double time = gameTime.ElapsedGameTime.TotalSeconds;

            // Draw without the synchronization
            GraphicsDevice.Clear(ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);

            Scene.PhysicsScene.Draw(time);

            if (EnableMenu)
            {
                GraphicsDevice.Clear(ClearOptions.DepthBuffer, Color.Black, 1.0f, 0);
                MenuScene.PhysicsScene.Draw(time);
            }

            // Update to the vertical retrace
            base.Draw(gameTime);
        }

#if !XBOX360
        protected override void EndDraw()
        {
            if (enablePrintScreen && (GraphicsDevice.GraphicsProfile == GraphicsProfile.HiDef))
            {
                int screenCount = 1;
                while (File.Exists("Screen" + screenCount.ToString("d3") + ".png"))
                    screenCount++;

                using (Texture2D backBufferTexture = new Texture2D(GraphicsDevice, GraphicsDevice.PresentationParameters.BackBufferWidth, GraphicsDevice.PresentationParameters.BackBufferHeight, false, SurfaceFormat.Color))
                {
                    Color[] data = new Color[backBufferTexture.Width * backBufferTexture.Height];

                    GraphicsDevice.GetBackBufferData<Color>(data);
                    backBufferTexture.SetData<Color>(data);

                    FileStream file = File.Create("Screen" + screenCount.ToString("d3") + ".png");

                    backBufferTexture.SaveAsPng(file, backBufferTexture.Width, backBufferTexture.Height);

                    file.Close();
                }

                enablePrintScreen = false;
            }

            base.EndDraw();
        }
#endif

        public void DrawInfo(DrawMethodArgs args)
        {
            PhysicsScene scene = Engine.Factory.PhysicsSceneManager.Get(args.OwnerIndex);

#if XBOX360
            int offsetX = 50;
            int offsetY = -20;
#else
            int offsetX = 0;
            int offsetY = 0;
#endif

            int physicsObjectCount = scene.TotalPhysicsObjectCount;
            int constraintCount = scene.TotalConstraintCount;
            int contactPointCount = scene.TotalContactPointCount;

            if (EnableMenu)
            {
                physicsObjectCount += MenuScene.PhysicsScene.TotalPhysicsObjectCount;
                constraintCount += MenuScene.PhysicsScene.TotalConstraintCount;
                contactPointCount += MenuScene.PhysicsScene.TotalContactPointCount;
            }

            infoDrawFPSNameBuilder.Remove(infoDrawFPSNameLength, infoDrawFPSNameBuilder.Length - infoDrawFPSNameLength);
            infoDrawFPSNameBuilder.Append((int)(scene.DrawFPS + 0.5f));

            infoPhysicsFPSNameBuilder.Remove(infoPhysicsFPSNameLength, infoPhysicsFPSNameBuilder.Length - infoPhysicsFPSNameLength);
            infoPhysicsFPSNameBuilder.Append((int)(scene.SimulationFPS + 0.5f));

            infoPhysicsObjectsNameBuilder.Remove(infoPhysicsObjectsNameLength, infoPhysicsObjectsNameBuilder.Length - infoPhysicsObjectsNameLength);
            infoPhysicsObjectsNameBuilder.Append(physicsObjectCount);

            infoConstraintsNameBuilder.Remove(infoConstraintsNameLength, infoConstraintsNameBuilder.Length - infoConstraintsNameLength);
            infoConstraintsNameBuilder.Append(constraintCount);

            infoContactPointsNameBuilder.Remove(infoContactPointsNameLength, infoContactPointsNameBuilder.Length - infoContactPointsNameLength);
            infoContactPointsNameBuilder.Append(contactPointCount);

            spriteBatch.Begin(SpriteSortMode.Texture, BlendState.AlphaBlend, SamplerState.LinearWrap, DepthStencilState.Default, RasterizerState.CullNone);

            infoDrawPosition.X = offsetX + 15;
            infoDrawPosition.Y = offsetY + 474;
            spriteBatch.DrawString(spriteFont, Scene.SceneInfo, infoDrawPosition, infoDrawColor);
            infoDrawPosition.Y = offsetY + 490;
            spriteBatch.DrawString(spriteFont, infoDrawFPSNameBuilder.ToString(), infoDrawPosition, infoDrawColor);
            infoDrawPosition.Y = offsetY + 505;
            spriteBatch.DrawString(spriteFont, infoPhysicsFPSNameBuilder.ToString(), infoDrawPosition, infoDrawColor);
            infoDrawPosition.Y = offsetY + 520;
            spriteBatch.DrawString(spriteFont, infoPhysicsObjectsNameBuilder.ToString(), infoDrawPosition, infoDrawColor);
            infoDrawPosition.Y = offsetY + 535;
            spriteBatch.DrawString(spriteFont, infoConstraintsNameBuilder.ToString(), infoDrawPosition, infoDrawColor);
            infoDrawPosition.Y = offsetY + 550;
            spriteBatch.DrawString(spriteFont, infoContactPointsNameBuilder.ToString(), infoDrawPosition, infoDrawColor);
            infoDrawPosition.Y = offsetY + 565;
            spriteBatch.DrawString(spriteFont, infoMenuName, infoDrawPosition, infoDrawColor);

            spriteBatch.End();
        }

        public static void CreateSharedShapes(Demo demo, PhysicsScene scene)
        {
            ShapePrimitive shapePrimitive = null;
            Shape shape = null;

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("Point");
            shapePrimitive.CreatePoint(0.0f, 0.0f, 0.0f);
            shape = scene.Factory.ShapeManager.Create("Point");
            shape.Set(shapePrimitive, Matrix.Identity, 0.1f);

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("Edge");
            shapePrimitive.CreateEdge(-Vector3.UnitY, Vector3.UnitY);
            shape = scene.Factory.ShapeManager.Create("Edge");
            shape.Set(shapePrimitive, Matrix.Identity, 0.1f);

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("Box");
            shapePrimitive.CreateBox(1.0f);
            shape = scene.Factory.ShapeManager.Create("Box");
            shape.Set(shapePrimitive, Matrix.Identity, 0.0f);

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("CylinderY");
            shapePrimitive.CreateCylinderY(2.0f, 1.0f);
            shape = scene.Factory.ShapeManager.Create("CylinderY");
            shape.Set(shapePrimitive, Matrix.Identity, 0.0f);

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("Sphere");
            shapePrimitive.CreateSphere(1.0f);
            shape = scene.Factory.ShapeManager.Create("Sphere");
            shape.Set(shapePrimitive, Matrix.Identity, 0.0f);


            /* BASKET ------------------------------------------------------------------------------------------*/

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("Basket");
            shapePrimitive.CreateConeX(3f, 10f);
            shape = scene.Factory.ShapeManager.Create("Basket");
            shape.Set(shapePrimitive, Matrix.Identity, 0.0f);

            // Declare and initialize the translation vector of geometrical center 
            // with negated value returned by GetCenterTranslation function
            // after use MoveToCenter function in TriangleMesh class for hemisphere
            Vector3 centerTranslation = new Vector3(0.0f, -0.02876594f, -0.5271618f);
            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("HemisphereZ");
            shapePrimitive.CreateHemisphereZ(1.0f);
            shape = scene.Factory.ShapeManager.Create("HemisphereZ");
            shape.Set(shapePrimitive, Matrix.CreateTranslation(centerTranslation), 0.0f);

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("ConeY");
            shapePrimitive.CreateConeY(2.0f, 1.0f);
            shape = scene.Factory.ShapeManager.Create("ConeY");
            shape.Set(shapePrimitive, Matrix.Identity, 0.0f);

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("CapsuleY");
            shapePrimitive.CreateCapsuleY(2.0f, 1.0f);
            shape = scene.Factory.ShapeManager.Create("CapsuleY");
            shape.Set(shapePrimitive, Matrix.Identity, 0.0f);

            TriangleMesh triangleMesh = null;
            triangleMesh = scene.Factory.TriangleMeshManager.Create("HemisphereZ");
            triangleMesh.CreateHemisphereZ(10, 20, 1.0f);
            triangleMesh.MoveToCenter();
            if (!demo.Meshes.ContainsKey("HemisphereZ"))
                demo.Meshes.Add("HemisphereZ", new DemoMesh(demo, triangleMesh, demo.Textures["Default"], Vector2.One, true, true, true, false, true, RasterizerState.CullClockwise, false));

            Vector3 point1, point2, point3;
            point1 = new Vector3(-1.0f, -1.0f, 0.0f);
            point2 = new Vector3(-1.0f, 1.0f, 0.0f);
            point3 = new Vector3(1.0f, 1.0f, 0.0f);

            triangleMesh = scene.Factory.TriangleMeshManager.Create("Triangle1");
            triangleMesh.CreateTriangle(point1, point2, point3);
            if (!demo.Meshes.ContainsKey("Triangle1"))
                demo.Meshes.Add("Triangle1", new DemoMesh(demo, triangleMesh, demo.Textures["Default"], Vector2.One, false, false, true, false, true, RasterizerState.CullNone, false));

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("Triangle1");
            shapePrimitive.CreateTriangle(point1, point2, point3);

            shape = scene.Factory.ShapeManager.Create("Triangle1");
            shape.Set(shapePrimitive, Matrix.Identity, 0.01f);

            point1 = new Vector3(1.0f, 1.0f, 0.0f);
            point2 = new Vector3(1.0f, -1.0f, 0.0f);
            point3 = new Vector3(-1.0f, -1.0f, 0.0f);

            triangleMesh = scene.Factory.TriangleMeshManager.Create("Triangle2");
            triangleMesh.CreateTriangle(point1, point2, point3);
            if (!demo.Meshes.ContainsKey("Triangle2"))
                demo.Meshes.Add("Triangle2", new DemoMesh(demo, triangleMesh, demo.Textures["Default"], Vector2.One, false, false, true, false, true, RasterizerState.CullNone, false));

            shapePrimitive = scene.Factory.ShapePrimitiveManager.Create("Triangle2");
            shapePrimitive.CreateTriangle(point1, point2, point3);

            shape = scene.Factory.ShapeManager.Create("Triangle2");
            shape.Set(shapePrimitive, Matrix.Identity, 0.01f);
        }
    }
}